package com.huiyun.project.pay.biz.handler.pay;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.URLUtil;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.domain.*;
import com.alipay.api.request.AlipayTradeCreateRequest;
import com.alipay.api.response.AlipayTradeCreateResponse;
import com.alipay.api.response.AlipayTradePayResponse;
import com.ijpay.alipay.AliPayApi;
import com.ijpay.alipay.AliPayApiConfigKit;
import com.huiyun.project.common.core.domain.R;
import com.huiyun.project.pay.biz.dto.PayOrderDto;
import com.huiyun.project.pay.biz.entity.PayChannel;
import com.huiyun.project.pay.biz.kit.PayConfigKit;
import com.huiyun.project.pay.biz.service.PayChannelService;
import com.huiyun.project.pay.client.vo.RefundReq;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.HashMap;
import java.util.Map;

@Component
@Slf4j
public class AliPayHandler {
    @Autowired
    private PayChannelService payChannelService;

    /**
     * app支付
     */
    @RequestMapping(value = "/appPay")
    @ResponseBody
    public R appPay(PayOrderDto payOrderDto) {
        try {
            PayConfigKit.init(payOrderDto.getChannelAppId());
            PayChannel payChannel = payChannelService.getByMchIdAndChannelAppId(payOrderDto.getMchId(), payOrderDto.getChannelAppId());
            JSONObject jsonObject = JSONObject.parseObject(payChannel.getParam());
            AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
            model.setBody(payOrderDto.getBody());//商品内容 可选
            model.setSubject(payOrderDto.getSubject());//订单标题 必填
            model.setOutTradeNo(payOrderDto.getMchOrderNo());//商户订单号
            model.setTotalAmount(Convert.toStr(payOrderDto.getAmount() / 100D));//金额单位元
            model.setProductCode("QUICK_MSECURITY_PAY");
            String orderInfo = AliPayApi.appPayToResponse(model, getNotifyUrl(jsonObject.getString("domain"), payOrderDto.getChannelAppId())).getBody();
            log.info("alipay app支付下单返回:{}", orderInfo);
            return R.ok(orderInfo);
        } catch (AlipayApiException e) {
            log.error(ExceptionUtils.getMessage(e));
            return R.failed("system error:" + e.getMessage());
        }
    }


    /**
     * 支付宝PC支付
     *
     * @param payOrderDto
     * @return pageForm页面表单
     */

    @RequestMapping(value = "/pcPay")
    @ResponseBody
    public R pcPay(PayOrderDto payOrderDto) {
        try {
            PayConfigKit.init(payOrderDto.getChannelAppId());
            PayChannel payChannel = payChannelService.getByMchIdAndChannelAppId(payOrderDto.getMchId(), payOrderDto.getChannelAppId());
            JSONObject jsonObject = JSONObject.parseObject(payChannel.getParam());
            Map<String, Object> result = new HashMap<>();
            String returnUrl = getRefundNotifyNotifyUrl(jsonObject.getString("domain"), payOrderDto.getChannelAppId());
            String notifyUrl = getNotifyUrl(jsonObject.getString("domain"), payOrderDto.getChannelAppId());
            AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
            model.setBody(payOrderDto.getBody());//商品内容 可选
            model.setSubject(payOrderDto.getSubject());//订单标题 必填
            model.setOutTradeNo(payOrderDto.getMchOrderNo());//商户订单号
            model.setTotalAmount(Convert.toStr(payOrderDto.getAmount()));//金额 单位元
            model.setProductCode(payOrderDto.getMchOrderNo());
            model.setPassbackParams(URLUtil.encode(payOrderDto.getMchOrderNo()));//公用回传参数，需要编码，会原样返回
            String pageForm = AliPayApi.wapPayStr(model, returnUrl, notifyUrl);
            result.put("pageForm", pageForm);//表单
            return R.ok(result);
        } catch (Exception e) {
            log.error(ExceptionUtils.getMessage(e));
            return R.failed("system error:" + e.getMessage());
        }
    }


    /**
     * 支付宝wapPay支付
     *
     * @param payOrderDto
     */
    public R wapPay(PayOrderDto payOrderDto) {
        Map<String, Object> result = new HashMap<>();
        try {
            PayConfigKit.init(payOrderDto.getChannelAppId());
            PayChannel payChannel = payChannelService.getByMchIdAndChannelAppId(payOrderDto.getMchId(), payOrderDto.getChannelAppId());
            JSONObject jsonObject = JSONObject.parseObject(payChannel.getParam());
            String returnUrl = getRefundNotifyNotifyUrl(jsonObject.getString("domain"), payOrderDto.getChannelAppId());
            String notifyUrl = getNotifyUrl(jsonObject.getString("domain"), payOrderDto.getChannelAppId());
            AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
            model.setBody(payOrderDto.getBody());//商品内容 可选
            model.setSubject(payOrderDto.getSubject());//订单标题 必填
            model.setOutTradeNo(payOrderDto.getMchOrderNo());//商户订单号
            model.setTotalAmount(Convert.toStr(payOrderDto.getAmount()));//金额 单位元
            model.setProductCode(payOrderDto.getMchOrderNo());
            model.setPassbackParams(URLUtil.encode(payOrderDto.getMchOrderNo()));//公用回传参数，需要编码，会原样返回
            String pageForm = AliPayApi.wapPayStr(model, returnUrl, notifyUrl);
            result.put("pageForm", pageForm);//表单
            return R.ok(result);
        } catch (Exception e) {
            log.error(ExceptionUtils.getMessage(e));
            return R.failed("system error:" + e.getMessage());
        }

    }

    /**
     * 支付宝 扫码付（当面付） 扫客户付款码
     *
     * @param payOrderDto
     */
    public R qrPay(PayOrderDto payOrderDto) {
        try {
            PayConfigKit.init(payOrderDto.getChannelAppId());
            PayChannel payChannel = payChannelService.getByMchIdAndChannelAppId(payOrderDto.getMchId(), payOrderDto.getChannelAppId());
            JSONObject jsonObject = JSONObject.parseObject(payChannel.getParam());
            String returnUrl = getRefundNotifyNotifyUrl(jsonObject.getString("domain"), payOrderDto.getChannelAppId());
            String notifyUrl = getNotifyUrl(jsonObject.getString("domain"), payOrderDto.getChannelAppId());
            AlipayTradePayModel model = new AlipayTradePayModel();
            model.setBody(payOrderDto.getBody());//商品内容 可选
            model.setSubject(payOrderDto.getSubject());//订单标题 必填
            model.setOutTradeNo(payOrderDto.getMchOrderNo());//商户订单号
            model.setTotalAmount(Convert.toStr(payOrderDto.getAmount()));//金额 单位元
            model.setProductCode(payOrderDto.getMchOrderNo());//当面付
            model.setAuthCode(payOrderDto.getParam1());//扩展参数 客户支付码
            model.setScene("bar_code");//扫码付
            AlipayTradePayResponse response = AliPayApi.tradePayToResponse(model, notifyUrl);
            return R.ok(response);
        } catch (Exception e) {
            log.error(ExceptionUtils.getMessage(e));
            return R.failed("system error:" + e.getMessage());
        }
    }


    /**
     * 支付宝 商户出示二维码 客户扫码
     *
     * @param payOrderDto
     */
    public R barPay(PayOrderDto payOrderDto) {
        try {
            PayConfigKit.init(payOrderDto.getChannelAppId());
            PayChannel payChannel = payChannelService.getByMchIdAndChannelAppId(payOrderDto.getMchId(), payOrderDto.getChannelAppId());
            JSONObject jsonObject = JSONObject.parseObject(payChannel.getParam());
            String returnUrl = getRefundNotifyNotifyUrl(jsonObject.getString("domain"), payOrderDto.getChannelAppId());
            String notifyUrl = getNotifyUrl(jsonObject.getString("domain"), payOrderDto.getChannelAppId());
            AlipayTradeCreateModel model = new AlipayTradeCreateModel();
            model.setBody(payOrderDto.getBody());//商品内容 可选
            model.setSubject(payOrderDto.getSubject());//订单标题 必填
            model.setOutTradeNo(payOrderDto.getMchOrderNo());//商户订单号
            model.setTotalAmount(Convert.toStr(payOrderDto.getAmount()));//金额 单位元
            model.setProductCode(payOrderDto.getMchOrderNo());//当面付
            AlipayTradeCreateRequest request = new AlipayTradeCreateRequest();
            request.setBizModel(model);
            request.setReturnUrl(returnUrl);
            request.setNotifyUrl(notifyUrl);
            AlipayTradeCreateResponse response = AliPayApiConfigKit.getAliPayApiConfig().getAliPayClient().execute(request);
            return R.ok(response);
        } catch (Exception e) {
            log.error(ExceptionUtils.getMessage(e));
            return R.failed("system error:" + e.getMessage());
        }
    }


    /**
     * 退款操作
     *
     * @param refundReq
     * @return
     */
    @SneakyThrows
    public String refund(RefundReq refundReq, PayChannel payChannel) {
        PayConfigKit.init(payChannel.getChannelAppId());
        Assert.notNull(payChannel, "无效的渠道配置信息");
        //JSONObject jsonObject = JSONObject.parseObject(payChannel.getParam());
        String channelId = payChannel.getChannelId();
        Assert.notBlank(channelId, "无效的渠道编号");
        AlipayTradeRefundModel model = new AlipayTradeRefundModel();
        model.setOutTradeNo(refundReq.getMchOrderNo());
        model.setRefundAmount(Convert.toStr(refundReq.getRefundAmount() / 100.00));
        model.setRefundReason(refundReq.getRefundDesc());
        return AliPayApi.tradeRefundToResponse(model).getBody();
    }


    /**
     * 支付通知
     *
     * @return
     */
    public String getNotifyUrl(String domain, String channelAppId) {
        return domain.concat("/gw/pay/aliPay/payNotify/" + channelAppId);
    }

    /**
     * 退款通知
     *
     * @return
     */
    public String getRefundNotifyNotifyUrl(String domain, String channelAppId) {
        return domain.concat("/gw/pay/wxPay/refundNotify/" + channelAppId);
    }

}
